﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace AAA.Base.Util.Reflection
{
    public class Builder
    {
/*
        private static bool IsImplemented(Type objectType, Type interfaceType)
        {
            foreach (Type thisType in objectType.GetInterfaces())
            {
                if (thisType is interfaceType)
                    return true;
            }
            return false;
        }
*/

        public static List<T> LoadClassesFromFile<T>(string strFilename)
        {
            List<T> lstReturn = new List<T>();
            Assembly asmb = null;
            object loadObject;

            try
            {
                asmb = Assembly.LoadFile(strFilename);

                foreach (var type in asmb.GetTypes())
                {

                    if (!type.IsClass || type.IsNotPublic)
                        continue;

                    loadObject = Activator.CreateInstance(type);

                    if (loadObject is T)
                    {
                        lstReturn.Add((T)loadObject);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return lstReturn;
        }

        public static List<T> LoadClasses<T>(string strPath)
        {
            List<T> lstReturn = new List<T>();
            List<T> lstLoaded;
            FileInfo[] filesInfo;
            Assembly asmb = null;
            object loadObject;

            try
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(strPath);
                filesInfo = directoryInfo.GetFiles("*.dll");

                for (int i = 0; i < filesInfo.Length; i++)
                {
                    try
                    {
                        lstLoaded = LoadClassesFromFile<T>(filesInfo[i].FullName);

                        foreach (T lib in lstLoaded)
                            lstReturn.Add(lib);
/*

                        asmb = Assembly.LoadFile(filesInfo[i].FullName);

                        foreach (var type in asmb.GetTypes()) 
                        { 

                            if (!type.IsClass || type.IsNotPublic) 
                                continue;

                            loadObject = Activator.CreateInstance(type);

                            if (loadObject is T)
                            {
                                lstReturn.Add((T)loadObject); 
                            } 
                        } 
*/
                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return lstReturn;
        }

        public static List<T> LoadLibrary<T>(string strPath)
        {
            List<T> lstReturn = new List<T>();
            FileInfo[] filesInfo;
            Assembly asmb = null;
            T loadType;
            string strNamespace;


            try
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(strPath);
                filesInfo = directoryInfo.GetFiles("*.dll");

                for (int i = 0; i < filesInfo.Length; i++)
                {
                    try
                    {
                        strNamespace = filesInfo[i].Name.Replace(".dll", "");
                        asmb = Assembly.LoadFile(filesInfo[i].FullName);
                        loadType = (T)asmb.CreateInstance(strNamespace + "." + strNamespace.Substring(strNamespace.LastIndexOf('.') + 1));

                        if (loadType == null)
                            continue;
                        lstReturn.Add(loadType);

                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return lstReturn;
        }

        public static T CreateInstance<T>(string strDllName, string strClassname)
        {
            T instance = default(T);

            try
            {
                Assembly asm = Assembly.LoadFrom(strDllName);

                if (asm == null)
                    return instance;

                instance = (T)asm.CreateInstance(strClassname);

                return instance;
            }
            catch (Exception ex)
            {
            }
            return instance;
        }        
    }
}
